import random
import time


class Character:
    def __init__(self, name, health, attack, defense):
        self.name = name
        self.max_health = health
        self.health = health
        self.attack = attack
        self.defense = defense
        self.inventory = []
        self.gold = 0
        self.quests = []
        self.level = 1
        self.xp = 0
        self.xp_to_next_level = 100
        self.killed_enemies = []  # 记录击杀的敌人

    def is_alive(self):
        return self.health > 0

    def take_damage(self, damage):
        actual_damage = max(1, damage - self.defense)
        self.health -= actual_damage
        print(f"{self.name}受到了{actual_damage}点伤害！")
        if not self.is_alive():
            self.health = 0
            print(f"{self.name}已死亡！")
        return actual_damage

    def heal(self, amount):
        self.health = min(self.max_health, self.health + amount)
        print(f"{self.name}恢复了{amount}点生命值！")

    def attack_enemy(self, enemy):
        damage = random.randint(self.attack // 2, self.attack)
        print(f"{self.name}对{enemy.name}发动攻击，造成{damage}点伤害！")
        return enemy.take_damage(damage)

    def add_item(self, item):
        self.inventory.append(item)
        print(f"{self.name}获得了物品：{item.name}！")

    def use_item(self, item_index):
        if 0 <= item_index < len(self.inventory):
            item = self.inventory.pop(item_index)
            item.use(self)
        else:
            print("无效的物品索引！")

    def show_status(self):
        print(f"\n{self.name}的状态：")
        print(f"等级：{self.level} ({self.xp}/{self.xp_to_next_level} XP)")
        print(f"生命值：{self.health}/{self.max_health}")
        print(f"攻击力：{self.attack}")
        print(f"防御力：{self.defense}")
        print(f"金币：{self.gold}")
        print("物品：", end="")
        if not self.inventory:
            print("无")
        else:
            print(", ".join([f"{i}.{item.name}" for i, item in enumerate(self.inventory)]))

        print("任务：")
        if not self.quests:
            print("无")
        else:
            for i, quest in enumerate(self.quests):
                status = "已完成" if quest.completed else "进行中"
                print(f"{i + 1}. {quest.name} - {status}")

    def gain_xp(self, amount):
        self.xp += amount
        print(f"获得了{amount}点经验值！")
        while self.xp >= self.xp_to_next_level:
            self.level_up()

    def level_up(self):
        self.level += 1
        self.xp -= self.xp_to_next_level
        self.xp_to_next_level = int(self.xp_to_next_level * 1.5)
        self.max_health += 10
        self.health = self.max_health
        self.attack += 3
        self.defense += 2
        print(f"恭喜！等级提升到{self.level}！")
        print(f"生命值上限增加10点，攻击力增加3点，防御力增加2点！")


class Item:
    def __init__(self, name, description, effect, value=0):
        self.name = name
        self.description = description
        self.effect = effect
        self.value = value

    def use(self, character):
        if self.effect == "heal":
            character.heal(20)
        elif self.effect == "big_heal":
            character.heal(50)
        elif self.effect == "attack_up":
            character.attack += 5
            print(f"{character.name}的攻击力永久提升了5点！")
        elif self.effect == "defense_up":
            character.defense += 5
            print(f"{character.name}的防御力永久提升了5点！")
        elif self.effect == "key":
            print(f"你使用了{self.name}，打开了一扇门！")
        elif self.effect == "xp":
            character.gain_xp(50)
        else:
            print(f"使用了{self.name}，但没有任何效果...")


class Quest:
    def __init__(self, name, description, target_item=None, target_enemy=None, reward_item=None, reward_xp=0,
                 reward_gold=0):
        self.name = name
        self.description = description
        self.target_item = target_item
        self.target_enemy = target_enemy
        self.reward_item = reward_item
        self.reward_xp = reward_xp
        self.reward_gold = reward_gold
        self.completed = False

    def check_progress(self, player):
        if self.completed:
            return True

        # 检查物品收集类任务
        if self.target_item and self.target_item in [item.name for item in player.inventory]:
            self.completed = True
            return True

        # 检查击杀敌人类任务
        if self.target_enemy and self.target_enemy in player.killed_enemies:
            self.completed = True
            return True

        return False

    def complete(self, player):
        if not self.completed:
            self.completed = True
            print(f"任务完成：{self.name}！")
            if self.reward_item:
                player.add_item(self.reward_item)
            if self.reward_xp > 0:
                player.gain_xp(self.reward_xp)
            if self.reward_gold > 0:
                player.gold += self.reward_gold
                print(f"获得了{self.reward_gold}金币！")
            return True
        return False


class Enemy:
    def __init__(self, name, health, attack, defense, gold_reward, xp_reward, item_drop=None):
        self.name = name
        self.max_health = health
        self.health = health
        self.attack = attack
        self.defense = defense
        self.gold_reward = gold_reward
        self.xp_reward = xp_reward
        self.item_drop = item_drop

    def is_alive(self):
        return self.health > 0

    def take_damage(self, damage):
        actual_damage = max(1, damage - self.defense)
        self.health -= actual_damage
        print(f"{self.name}受到了{actual_damage}点伤害！")
        if not self.is_alive():
            self.health = 0
            print(f"{self.name}被击败了！")
        return actual_damage

    def attack_player(self, player):
        damage = random.randint(self.attack // 2, self.attack)
        print(f"{self.name}对{player.name}发动攻击，造成{damage}点伤害！")
        return player.take_damage(damage)


class NPC:
    def __init__(self, name, dialogue, quest=None, trade_items=None):
        self.name = name
        self.dialogue = dialogue
        self.quest = quest
        self.trade_items = trade_items or []

    def talk(self, player):
        print(f"\n{self.name}: {self.dialogue}")

        if self.quest and self.quest not in player.quests:
            accept = input(f"{self.name}想要给你一个任务：{self.quest.name}。接受吗？(y/n) ").lower()
            if accept == 'y':
                player.quests.append(self.quest)
                print(f"你接受了任务：{self.quest.name}！")

        if self.trade_items:
            trade = input("想要交易吗？(y/n) ").lower()
            if trade == 'y':
                self.trade(player)

    def trade(self, player):
        print(f"\n{self.name}的商店：")
        for i, item in enumerate(self.trade_items):
            print(f"{i + 1}. {item.name} - {item.description} (价格: {item.value}金币)")

        while True:
            choice = input("选择要购买的物品编号（或输入q退出）：").lower()
            if choice == 'q':
                break

            try:
                item_index = int(choice) - 1
                if 0 <= item_index < len(self.trade_items):
                    item = self.trade_items[item_index]
                    if player.gold >= item.value:
                        player.gold -= item.value
                        player.add_item(item)
                        print(f"你购买了{item.name}，花费了{item.value}金币！")
                    else:
                        print("金币不足！")
                else:
                    print("无效的选择！")
            except ValueError:
                print("无效的输入！")


class Room:
    def __init__(self, name, description, exits, items=None, enemy=None, npc=None, locked=False):
        self.name = name
        self.description = description
        self.exits = exits
        self.items = items if items else []
        self.enemy = enemy
        self.npc = npc
        self.locked = locked
        self.visited = False

    def enter(self, player):
        if not self.visited:
            print(f"\n你进入了{self.name}。")
            print(self.description)
            self.visited = True
        else:
            print(f"\n你回到了{self.name}。")

        if self.enemy and self.enemy.is_alive():
            print(f"这里有一个{self.enemy.name}！")
            self.battle(player, self.enemy)

        if self.items:
            print("你发现了以下物品：")
            for i, item in enumerate(self.items):
                print(f"{i + 1}. {item.name} - {item.description}")
            take = input("要拾取这些物品吗？(y/n) ").lower()
            if take == 'y':
                for item in self.items:
                    player.add_item(item)
                self.items = []

        if self.npc:
            talk = input(f"这里有一个{self.npc.name}。要和他交谈吗？(y/n) ").lower()
            if talk == 'y':
                self.npc.talk(player)

        if self.locked:
            print("这个出口被锁住了！")
            if any(item.effect == "key" for item in player.inventory):
                use_key = input("你有钥匙，要使用吗？(y/n) ").lower()
                if use_key == 'y':
                    for i, item in enumerate(player.inventory):
                        if item.effect == "key":
                            player.use_item(i)
                            self.locked = False
                            print("门被打开了！")
                            break
            else:
                print("你需要找到钥匙才能打开这个门。")

    def battle(self, player, enemy):
        print("\n战斗开始！")
        while player.is_alive() and enemy.is_alive():
            print("\n--- 回合开始 ---")
            player.show_status()
            print(f"{enemy.name}的生命值：{enemy.health}/{enemy.max_health}")

            print("\n你的行动：")
            print("1. 攻击")
            print("2. 使用物品")
            print("3. 查看状态")
            print("4. 尝试逃跑")

            choice = input("请选择：").strip()

            if choice == '1':
                player.attack_enemy(enemy)
                if enemy.is_alive():
                    enemy.attack_player(player)
            elif choice == '2':
                if not player.inventory:
                    print("你没有任何物品！")
                    enemy.attack_player(player)
                else:
                    print("你的物品：")
                    for i, item in enumerate(player.inventory):
                        print(f"{i}. {item.name} - {item.description}")
                    item_choice = input("选择要使用的物品索引（或输入q取消）：")
                    if item_choice.lower() != 'q':
                        try:
                            player.use_item(int(item_choice))
                            if enemy.is_alive():
                                enemy.attack_player(player)
                        except ValueError:
                            print("无效的选择！")
                            enemy.attack_player(player)
            elif choice == '3':
                player.show_status()
                input("按Enter继续...")
            elif choice == '4':
                escape_chance = random.randint(1, 10)
                if escape_chance > 3:
                    print("你成功逃脱了战斗！")
                    return
                else:
                    print("逃跑失败！")
                    enemy.attack_player(player)
            else:
                print("无效的选择！")
                if enemy.is_alive():
                    enemy.attack_player(player)

            if not enemy.is_alive():
                player.killed_enemies.append(enemy.name)  # 记录击杀的敌人
                print(f"你击败了{enemy.name}！")
                player.gold += enemy.gold_reward
                player.gain_xp(enemy.xp_reward)
                print(f"获得了{enemy.gold_reward}金币和{enemy.xp_reward}点经验值！")
                if enemy.item_drop and random.random() < 0.5:  # 50%几率掉落物品
                    dropped_item = enemy.item_drop
                    player.add_item(dropped_item)
                    print(f"{enemy.name}掉落了{dropped_item.name}！")

                # 检查任务进度
                for quest in player.quests:
                    if quest.target_enemy == enemy.name and not quest.completed:
                        quest.check_progress(player)
                        if quest.completed:
                            quest.complete(player)
                break


def create_game_world():
    # 创建物品
    health_potion = Item("治疗药水", "恢复20点生命值", "heal", 10)
    big_health_potion = Item("高级治疗药水", "恢复50点生命值", "big_heal", 25)
    strength_potion = Item("力量药水", "永久提升5点攻击力", "attack_up", 30)
    defense_potion = Item("防御药水", "永久提升5点防御力", "defense_up", 30)
    xp_potion = Item("经验药水", "获得50点经验值", "xp", 20)
    key = Item("生锈的钥匙", "可以打开锁住的门", "key")
    master_key = Item("城堡主钥匙", "可以打开所有锁住的门", "key")
    ancient_map = Item("古老地图", "显示城堡的秘密通道", "map")
    treasure = Item("黄金宝藏", "价值连城的宝藏", "treasure", 100)

    # 创建敌人
    skeleton = Enemy("骷髅", 30, 8, 3, 10, 20)
    zombie = Enemy("僵尸", 40, 6, 5, 15, 25)
    spider = Enemy("巨型蜘蛛", 25, 10, 2, 12, 20, health_potion)
    guard = Enemy("城堡守卫", 60, 12, 8, 30, 40, strength_potion)
    mage = Enemy("黑暗法师", 50, 15, 5, 40, 50, xp_potion)
    minotaur = Enemy("牛头人", 80, 18, 10, 50, 60, defense_potion)
    boss = Enemy("城堡领主", 120, 20, 15, 100, 100, master_key)

    # 创建NPC
    old_man = NPC(
        "老巫师",
        "欢迎来到这座古老的城堡，年轻的冒险者。我可以给你一些任务，如果你愿意的话。",
        Quest(
            "清除城堡守卫",
            "消灭城堡中的所有守卫",
            target_enemy="城堡守卫",
            reward_item=ancient_map,
            reward_xp=100,
            reward_gold=50
        ),
        [health_potion, strength_potion, defense_potion]
    )

    merchant = NPC(
        "商人",
        "需要什么装备吗？我这里有各种好东西。",
        trade_items=[health_potion, big_health_potion, strength_potion, defense_potion, xp_potion]
    )

    # 创建任务
    find_treasure = Quest(
        "寻找宝藏",
        "在城堡中找到黄金宝藏",
        target_item="黄金宝藏",
        reward_xp=200,
        reward_gold=200
    )

    kill_boss = Quest(
        "击败城堡领主",
        "击败城堡领主，结束他的统治",
        target_enemy="城堡领主",
        reward_item=Item("勇者勋章", "证明你是一名伟大的冒险者", "medal"),
        reward_xp=300,
        reward_gold=300
    )

    # 创建房间
    entrance = Room(
        "城堡入口",
        "你站在一座古老城堡的入口。周围是破败的墙壁，前方有一条走廊通向城堡内部。",
        {"北": "走廊", "南": "离开城堡"}
    )

    corridor = Room(
        "走廊",
        "一条长长的走廊，两侧有几扇门。空气中弥漫着一股霉味。",
        {"北": "大厅", "南": "城堡入口", "东": "储藏室", "西": "武器库"},
        [Item("金币", "5枚金币", "gold")]
    )

    storage = Room(
        "储藏室",
        "一个堆满杂物的房间。看起来已经很久没有人来过了。",
        {"西": "走廊"},
        [health_potion, Item("金币", "10枚金币", "gold")]
    )

    armory = Room(
        "武器库",
        "房间里摆满了各种武器和盔甲。",
        {"东": "走廊"},
        [strength_potion],
        skeleton
    )

    great_hall = Room(
        "大厅",
        "一个宽敞的大厅，天花板很高。大厅中央有一个楼梯通向二楼。",
        {"北": "楼梯", "南": "走廊", "东": "餐厅", "西": "书房"},
        [Item("金币", "15枚金币", "gold")],
        zombie,
        old_man
    )

    dining_room = Room(
        "餐厅",
        "一张长长的餐桌占据了房间的中央，上面摆满了发霉的食物。",
        {"西": "大厅"},
        [defense_potion]
    )

    library = Room(
        "书房",
        "房间里有许多书架，上面摆满了古老的书籍。",
        {"东": "大厅"},
        [key]
    )

    stairs = Room(
        "楼梯",
        "一段古老的楼梯通向二楼。楼梯看起来有些破旧，走在上面会发出咯吱声。",
        {"北": "二楼走廊", "南": "大厅"}
    )

    second_floor_corridor = Room(
        "二楼走廊",
        "二楼的走廊比一楼窄小，光线也更昏暗。",
        {"北": "主卧", "南": "楼梯", "东": "客房", "西": "阳台"},
        locked=True
    )

    master_bedroom = Room(
        "主卧",
        "一个豪华的卧室，中央有一张大床。看起来这里曾经住着城堡的主人。",
        {"南": "二楼走廊"},
        [Item("金币", "25枚金币", "gold"), health_potion, strength_potion],
        boss
    )

    guest_room = Room(
        "客房",
        "一个简单的房间，有一张床和一个衣柜。",
        {"西": "二楼走廊"},
        [health_potion, defense_potion]
    )

    balcony = Room(
        "阳台",
        "一个小阳台，可以俯瞰城堡外的庭院。",
        {"东": "二楼走廊"},
        [Item("金币", "20枚金币", "gold")],
        spider
    )

    # 新增区域：地下墓穴
    basement_stairs = Room(
        "地下室楼梯",
        "一段陡峭的楼梯通向城堡的地下室。空气中弥漫着一股腐臭味。",
        {"北": "地下墓穴", "南": "大厅"},
        locked=True
    )

    catacombs = Room(
        "地下墓穴",
        "一个阴暗的墓穴，周围是一排排的棺材。",
        {"北": "墓室", "南": "地下室楼梯", "东": "秘密通道"},
        [xp_potion],
        minotaur
    )

    tomb = Room(
        "墓室",
        "中央有一个巨大的石棺，上面刻满了神秘的符文。",
        {"南": "地下墓穴"},
        [treasure],
        mage
    )

    secret_passage = Room(
        "秘密通道",
        "一条狭窄的通道，似乎通向城堡的其他区域。",
        {"西": "地下墓穴", "东": "隐藏宝库"},
        locked=True
    )

    hidden_treasure = Room(
        "隐藏宝库",
        "一个小房间，里面堆满了金银财宝！",
        {"西": "秘密通道"},
        [
            Item("金币", "50枚金币", "gold"),
            big_health_potion,
            strength_potion,
            defense_potion
        ]
    )

    # 创建游戏世界字典
    world = {
        "城堡入口": entrance,
        "走廊": corridor,
        "储藏室": storage,
        "武器库": armory,
        "大厅": great_hall,
        "餐厅": dining_room,
        "书房": library,
        "楼梯": stairs,
        "二楼走廊": second_floor_corridor,
        "主卧": master_bedroom,
        "客房": guest_room,
        "阳台": balcony,
        "地下室楼梯": basement_stairs,
        "地下墓穴": catacombs,
        "墓室": tomb,
        "秘密通道": secret_passage,
        "隐藏宝库": hidden_treasure
    }

    # 返回游戏世界和任务
    return world, find_treasure, kill_boss


def play_game():
    print("欢迎来到《神秘城堡探险》！")
    try:
        name = input("请输入你的名字：").strip()
        if not name:
            name = "冒险者"
        print(f"\n{name}，你的冒险即将开始！")
        print("你听说了一座古老城堡的传说，据说里面藏着巨大的宝藏。你决定前来一探究竟...")

        # 创建玩家
        player = Character(name, 100, 15, 5)

        # 创建游戏世界和获取任务
        world, find_treasure, kill_boss = create_game_world()

        # 添加初始任务
        player.quests.append(Quest(
            "探索城堡",
            "探索城堡的各个角落，寻找宝藏和线索",
            reward_xp=50,
            reward_gold=20
        ))
        player.quests.append(find_treasure)
        player.quests.append(kill_boss)

        # 从城堡入口开始游戏
        current_room = world["城堡入口"]
        current_room.enter(player)

        while player.is_alive():
            print("\n---")
            print(f"当前位置：{current_room.name}")
            print("可用的出口：", end="")
            print(", ".join([f"{direction} ({room_name})" for direction, room_name in current_room.exits.items()]))

            if current_room.name == "城堡入口" and "南" in current_room.exits:
                print("输入'南'离开城堡，结束游戏。")

            command = input("\n你想做什么？ ").lower().strip()

            if command in ["q", "quit", "exit"]:
                print("你决定放弃探险，离开了城堡。")
                break

            if command == "status":
                player.show_status()
                continue

            if command == "help":
                print("\n可用命令：")
                print("- 方向（北、南、东、西）：移动到指定方向的房间")
                print("- status：查看你的状态和物品")
                print("- help：显示帮助信息")
                print("- q/quit/exit：退出游戏")
                continue

            if command in current_room.exits:
                next_room_name = current_room.exits[command]

                if next_room_name == "离开城堡":
                    # 检查任务完成情况
                    completed_quests = [q for q in player.quests if q.completed]
                    print(f"\n你成功离开了城堡！你完成了{len(completed_quests)}/{len(player.quests)}个任务。")
                    print(f"你的冒险结束了。你获得了{player.gold}枚金币和以下物品：")
                    if player.inventory:
                        for item in player.inventory:
                            print(f"- {item.name}")
                    else:
                        print("无")
                    break

                next_room = world.get(next_room_name)
                if next_room:
                    if next_room.locked:
                        print("这个出口被锁住了！")
                        continue
                    current_room = next_room
                    current_room.enter(player)
                else:
                    print("那个方向没有房间！")
            else:
                print("无效的命令！输入'help'查看可用命令。")

    except Exception as e:
        print(f"\n游戏崩溃了！错误信息：{str(e)}")
        import traceback
        print("\n完整错误堆栈：")
        traceback.print_exc()
    finally:
        print("\n游戏结束！感谢游玩《神秘城堡探险》！")


if __name__ == "__main__":
    play_game()